<template>
  <div class="new-ssh-terminal">
    <!-- 终端头部 -->
    <div class="terminal-header glass-dialog">
      <div class="header-left">
        <div class="host-info">
          <i class="el-icon-monitor"></i>
          <span class="hostname">{{ hostInfo.hostname }}</span>
          <span class="host-ip">({{ hostInfo.public_ip }}:{{ hostInfo.port }})</span>
        </div>
        <div class="connection-status">
          <span :class="['status-indicator', connectionStatus]"></span>
          <span class="status-text">{{ getStatusText() }}</span>
        </div>
      </div>

      <div class="header-right">
        <div class="session-info" v-if="connectionId">
          <span class="session-time">{{ formatDuration(sessionDuration) }}</span>
        </div>
        <div class="controls">
          <!-- 连接按钮 - 始终显示 -->
          <el-button v-if="connectionStatus !== 'connected'"
            size="small" type="primary" @click="connect"
            :disabled="connecting" :loading="connecting">
            {{ connecting ? '连接中...' : connectionStatus === 'disconnected' ? '重新连接' : '连接' }}
          </el-button>
          <!-- 断开按钮 -->
          <el-button size="small" type="danger" @click="disconnect" :disabled="connectionStatus !== 'connected'">
            断开
          </el-button>
          <!-- 文件传输按钮 -->
          <el-button size="small" @click="showFileTransferDialog" :disabled="connectionStatus !== 'connected'" class="file-transfer-btn">
            <i class="fa fa-file-upload"></i> 文件传输
          </el-button>
        </div>
      </div>
    </div>

    <!-- 终端容器 -->
    <div ref="terminalContainer" class="terminal-container glass-dialog"
         @dragover="handleDragOver"
         @dragleave="handleDragLeave"
         @drop="handleDrop"
         :class="{ 'drag-over': isDragOver }">
      <div ref="terminal" class="xterm-container"></div>

      <!-- 拖拽提示层 -->
      <div v-if="isDragOver" class="drag-overlay glass-dialog">
        <div class="drag-content">
          <i class="fa fa-cloud-upload-alt drag-icon"></i>
          <h3>拖拽文件到此处上传</h3>
          <p>支持多文件上传，将自动使用rz命令</p>
        </div>
      </div>
    </div>

    <!-- 状态栏 -->
    <div class="status-bar glass-dialog">
      <div class="status-left">
        <span class="connection-id" v-if="connectionId">连接ID: {{ connectionId }}</span>
        <span class="user-info">用户: {{ hostInfo.username }}</span>
      </div>
      <div class="status-right">
        <span class="terminal-size">{{ terminalSize.cols }}x{{ terminalSize.rows }}</span>
        <span class="encoding">UTF-8</span>
      </div>
    </div>

    <!-- 文件传输对话框 -->
    <el-dialog
      v-model="fileTransferDialog"
      :title="transferType === 'upload' ? '文件上传' : '文件下载'"
      width="600px"
      class="glass-dialog"
      :show-close="true"
      @close="closeFileTransferDialog">

      <div class="file-transfer-content">
        <!-- 上传区域 -->
        <div v-if="transferType === 'upload'" class="upload-area glass-panel">
          <div class="upload-drop-zone"
               @dragover="handleDragOver"
               @dragleave="handleDragLeave"
               @drop="handleDrop">
            <i class="fa fa-cloud-upload-alt upload-icon"></i>
            <h4>拖拽文件到此处或点击选择</h4>
            <p>支持多文件上传，将使用rz命令传输</p>
            <input type="file" multiple @change="handleFileSelect" style="display: none;" ref="fileInput">
            <el-button type="primary" @click="$refs.fileInput.click()" class="glass-button">
              选择文件
            </el-button>
          </div>
        </div>

        <!-- 传输进度 -->
        <div v-if="transferFiles.length > 0" class="transfer-progress glass-panel">
          <h4>传输进度</h4>
          <div v-for="(file, index) in transferFiles" :key="index" class="file-item">
            <div class="file-info">
              <span class="file-name">{{ file.name }}</span>
              <span class="file-size">({{ formatFileSize(file.size) }})</span>
              <span class="file-status" :class="file.status">{{ getFileStatusText(file.status) }}</span>
            </div>
            <el-progress
              :percentage="file.progress"
              :status="file.status === 'completed' ? 'success' : file.status === 'error' ? 'exception' : ''"
              :stroke-width="6"
              class="file-progress">
            </el-progress>
          </div>
        </div>

        <!-- 下载区域 -->
        <div v-if="transferType === 'download'" class="download-area glass-panel">
          <div class="download-header">
            <h4>文件浏览器</h4>
            <div class="path-bar">
              <el-input
                v-model="fileBrowser.currentPath"
                placeholder="当前路径"
                class="glass-input path-input"
                @keyup.enter="loadFileList"
                @input="handlePathInput"
                @blur="loadFileList">
                <template #prepend>
                  <i class="fa fa-folder"></i>
                </template>
                <template #append>
                  <el-button @click="loadFileList" :loading="fileBrowser.loading" class="path-refresh-btn">
                    <i class="fa fa-refresh"></i>
                  </el-button>
                </template>
              </el-input>
            </div>
          </div>

          <!-- 文件列表 -->
          <div class="file-list" v-loading="fileBrowser.loading">
            <div class="file-list-header">
              <el-button size="small" @click="goToParentDirectory" :disabled="fileBrowser.currentPath === '/'" class="file-nav-button">
                <i class="fa fa-arrow-up"></i> 上级目录
              </el-button>
              <el-button size="small" @click="loadFileList" class="file-nav-button">
                <i class="fa fa-refresh"></i> 刷新
              </el-button>
            </div>

            <div class="file-items">
              <div
                v-for="file in fileBrowser.files"
                :key="file.name"
                class="file-item-row"
                :class="{ 'selected': fileBrowser.selectedFiles.includes(file.path) }"
                @click="selectFile(file)"
                @dblclick="handleFileDoubleClick(file)">

                <div class="file-icon">
                  <i :class="getFileIcon(file)" :style="{ color: getFileColor(file) }"></i>
                </div>

                <div class="file-info">
                  <div class="file-name">{{ file.name }}</div>
                  <div class="file-details">
                    <span class="file-size">{{ file.type === 'directory' ? '-' : formatFileSize(file.size) }}</span>
                    <span class="file-time">{{ formatFileTime(file.modified) }}</span>
                    <span class="file-permissions">{{ file.permissions }}</span>
                  </div>
                </div>

                <div class="file-actions" v-if="file.type === 'file'">
                  <el-button size="small" @click.stop="downloadSingleFile(file)" class="file-download-btn">
                    <i class="fa fa-download"></i>
                  </el-button>
                </div>
              </div>
            </div>
          </div>

          <!-- 批量下载 -->
          <div class="download-actions" v-if="fileBrowser.selectedFiles.length > 0">
            <el-button type="primary" @click="downloadSelectedFiles" class="glass-button">
              <i class="fa fa-download"></i> 下载选中文件 ({{ fileBrowser.selectedFiles.length }})
            </el-button>
          </div>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeFileTransferDialog" class="glass-button">关闭</el-button>
          <el-button v-if="transferType === 'upload'" type="primary" @click="switchToDownload" class="glass-button">
            切换到下载
          </el-button>
          <el-button v-else type="primary" @click="switchToUpload" class="glass-button">
            切换到上传
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import axios from 'axios'
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
import { SearchAddon } from 'xterm-addon-search'
import { WebLinksAddon } from 'xterm-addon-web-links'
import 'xterm/css/xterm.css'

export default {
  name: 'NewSSHTerminal',
  props: {
    hostInfo: {
      type: Object,
      required: true
    },
    accessToken: {
      type: String,
      default: null
    },
    connectionId: {
      type: String,
      default: null
    },
    hideConnectButton: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      terminal: null,
      fitAddon: null,
      webLinksAddon: null,
      searchAddon: null,
      websocket: null,
      connectionStatus: 'disconnected', // disconnected, connecting, connected, error
      connecting: false,
      connectionId: null,
      sessionStartTime: null,
      sessionDuration: 0,
      durationTimer: null,

      terminalSize: { cols: 80, rows: 24 },
      reconnectAttempts: 0,
      maxReconnectAttempts: 3,

      // 文件传输相关
      isDragOver: false,
      isUploading: false,
      uploadProgress: 0,
      uploadQueue: [],
      fileTransferDialog: false,
      transferType: 'upload', // upload, download
      transferFiles: [],
      currentTransfer: null,
      downloadFilename: '',
      // 文件浏览器相关
      fileBrowser: {
        visible: false,
        loading: false,
        currentPath: '~',
        files: [],
        selectedFiles: []
      },
      // 当前工作目录
      currentWorkingDirectory: '~',
      // 临时输出处理器
      tempOutputHandler: null,
      // 路径输入防抖定时器
      pathInputTimer: null
    }
  },
  mounted() {
    this.initTerminal()
    this.startDurationTimer()

    // 监听ESC键退出全屏
    document.addEventListener('keydown', this.handleKeydown)

    // 监听窗口大小变化
    window.addEventListener('resize', this.handleResize)

    // 如果有访问令牌，自动连接
    if (this.accessToken) {
      setTimeout(() => {
        this.connect()
      }, 1000) // 延迟1秒确保终端完全初始化
    }
  },
  beforeDestroy() {
    this.cleanup()
    document.removeEventListener('keydown', this.handleKeydown)
    window.removeEventListener('resize', this.handleResize)
  },
  methods: {
    initTerminal() {
      // 创建终端实例 - 完全原生Linux终端配置
      // 使用标准ANSI颜色配置
      this.terminal = new Terminal({
        cursorBlink: true,
        cursorStyle: 'block',
        fontSize: 14,
        fontFamily: 'Monaco, Menlo, "Ubuntu Mono", "Consolas", monospace',
        theme: {
          background: '#000000',
          foreground: '#ffffff',
          cursor: '#ffffff',
          selection: '#3e3e3e',
          // 标准ANSI颜色
          black: '#000000',
          red: '#cd0000',
          green: '#00cd00',
          yellow: '#cdcd00',
          blue: '#0000ee',
          magenta: '#cd00cd',
          cyan: '#00cdcd',
          white: '#e5e5e5',
          brightBlack: '#7f7f7f',
          brightRed: '#ff0000',
          brightGreen: '#00ff00',
          brightYellow: '#ffff00',
          brightBlue: '#5c5cff',
          brightMagenta: '#ff00ff',
          brightCyan: '#00ffff',
          brightWhite: '#ffffff'
        },
        // 不设置固定的cols和rows，让fitAddon自动计算
        scrollback: 1000,
        allowTransparency: false,
        convertEol: true
      })

      // 添加插件
      this.fitAddon = new FitAddon()
      this.webLinksAddon = new WebLinksAddon()
      this.searchAddon = new SearchAddon()

      this.terminal.loadAddon(this.fitAddon)
      this.terminal.loadAddon(this.webLinksAddon)
      this.terminal.loadAddon(this.searchAddon)

      // 打开终端
      this.terminal.open(this.$refs.terminal)

      // 等待DOM完全渲染后再计算尺寸
      this.$nextTick(() => {
        setTimeout(() => {
          this.fitTerminal()
          // 更新终端尺寸状态
          this.terminalSize = {
            cols: this.terminal.cols,
            rows: this.terminal.rows
          }
          console.log('终端初始化完成，尺寸:', this.terminalSize)
        }, 100)
      })

      // 暴露terminal实例到window对象用于调试
      window.currentTerminal = this.terminal

      // 监听用户输入
      this.terminal.onData(this.handleTerminalInput)

      // 监听终端大小变化
      this.terminal.onResize(this.handleTerminalResize)

      // 显示简洁的连接提示
      this.showConnectionPrompt()
    },

    showConnectionPrompt() {
      this.terminal.writeln(`\x1b[32mSSH Terminal Ready\x1b[0m`)
      this.terminal.writeln(`\x1b[90mTarget: ${this.hostInfo.username}@${this.hostInfo.hostname}:${this.hostInfo.port}\x1b[0m`)
      this.terminal.writeln('')
    },

    async connect() {
      if (this.connecting || this.connectionStatus === 'connected') {
        return
      }

      this.connecting = true
      this.connectionStatus = 'connecting'
      this.reconnectAttempts = 0
      this.$emit('connection-status', this.connectionId, 'connecting')

      try {
        // 如果没有访问令牌，先获取
        if (!this.accessToken) {
          const response = await axios.post('/api/ssh/request-access/', {
            host_id: this.hostInfo.id
          })

          if (response.data.success) {
            // 通知父组件更新访问令牌
            this.$emit('token-updated', this.connectionId, response.data.access_token)
          } else {
            throw new Error(response.data.message || '无权访问此主机')
          }
        }

        await this.establishWebSocketConnection()
        this.connectionStatus = 'connected'
        this.$emit('connection-status', this.connectionId, 'connected')
      } catch (error) {
        console.error('连接失败:', error)
        this.connectionStatus = 'disconnected'
        this.$emit('connection-status', this.connectionId, 'disconnected')
        this.handleConnectionError(error.message || '连接失败')
      } finally {
        this.connecting = false
      }
    },

    async establishWebSocketConnection() {
      try {
        // 获取认证token（这里使用localStorage中的token作为session key）
        const token = localStorage.getItem('token')
        if (!token) {
          throw new Error('未找到认证token，请重新登录')
        }

        // 获取访问令牌，优先使用props，然后尝试URL参数
        let accessToken = this.accessToken
        if (!accessToken) {
          const urlParams = new URLSearchParams(window.location.search)
          accessToken = urlParams.get('token')
        }

        if (!accessToken) {
          throw new Error('缺少访问令牌，请通过正确的方式访问SSH终端')
        }

        console.log('使用访问令牌:', accessToken ? '已获取' : '未获取')

        // 使用统一的WebSocket配置工具
        const websocketConfig = await import('@/utils/websocket-config')
        const wsUrl = websocketConfig.getSSHWebSocketUrl(this.hostInfo.id, accessToken)

        return new Promise((resolve, reject) => {
          this.createWebSocketConnection(wsUrl, resolve, reject)
        })
      } catch (error) {
        console.error('连接SSH失败:', error)
        ElMessage.error('连接SSH失败: ' + error.message)
        this.connectionStatus = 'error'
        this.connecting = false
        throw error
      }
    },

    createWebSocketConnection(wsUrl, resolve, reject) {
      try {
        console.log('尝试连接WebSocket:', wsUrl)

        // 创建WebSocket连接
        this.websocket = new WebSocket(wsUrl)

        this.websocket.onopen = () => {
          // 发送连接请求
          this.websocket.send(JSON.stringify({
            type: 'connect'
          }))
        }

        this.websocket.onmessage = (event) => {
          try {
            const data = JSON.parse(event.data)
            this.handleWebSocketMessage(data, resolve, reject)
          } catch (error) {
            console.error('解析WebSocket消息失败:', error)
          }
        }

        this.websocket.onclose = (event) => {
          console.log('WebSocket关闭事件:', event.code, event.reason, event.wasClean)
          this.terminal.writeln(`\x1b[31mWebSocket连接关闭: 代码=${event.code}, 原因=${event.reason || '无'}\x1b[0m`)
          this.handleWebSocketClose(event)
          if (this.connectionStatus === 'connecting') {
            reject(new Error(`WebSocket连接关闭: ${event.code} ${event.reason || ''}`))
          }
        }

        this.websocket.onerror = (error) => {
          console.error('WebSocket错误:', error)
          this.terminal.writeln('\x1b[31mWebSocket连接错误\x1b[0m')
          this.handleConnectionError('WebSocket连接错误')
          reject(error)
        }
      } catch (error) {
        console.error('创建WebSocket连接失败:', error)
        reject(error)
      }
    },

    handleWebSocketMessage(data, resolve, reject) {
      switch (data.type) {
        case 'status':
          if (data.status === 'websocket_connected') {
            // WebSocket连接成功，等待SSH连接
          }
          break

        case 'connected':
          // SSH连接成功
          this.connectionStatus = 'connected'
          this.connectionId = data.connection_id
          this.sessionStartTime = new Date()
          // 不清屏，保留之前的内容和颜色测试
          // 不显示连接成功信息，直接显示shell输出

          // 连接成功后立即发送正确的终端尺寸
          this.$nextTick(() => {
            setTimeout(() => {
              if (this.terminal && this.websocket) {
                this.websocket.send(JSON.stringify({
                  type: 'resize',
                  cols: this.terminal.cols,
                  rows: this.terminal.rows
                }))
                console.log('SSH连接成功后发送终端尺寸:', this.terminal.cols, 'x', this.terminal.rows)
              }
            }, 200)
          })

          if (resolve) resolve()
          break

        case 'output':
          // 检查是否有临时输出处理器
          if (this.tempOutputHandler) {
            this.tempOutputHandler(data)
          } else {
            // 过滤掉不必要的系统消息，但保留登录信息和shell提示符
            const filteredOutput = this.filterSystemMessages(data.data)
            if (filteredOutput) {
              // 对于大量数据，分批写入终端以避免阻塞
              this.writeToTerminalBatched(filteredOutput)
            }
          }
          break

        case 'error':
          // 连接错误
          this.handleConnectionError(data.message)
          if (reject) reject(new Error(data.message))
          break

        default:
          console.log('未知消息类型:', data.type)
      }
    },

    handleWebSocketClose(event) {
      console.log('WebSocket连接关闭:', event.code, event.reason)

      if (this.connectionStatus === 'connected') {
        this.connectionStatus = 'disconnected'
        this.terminal.writeln('\r\n\x1b[1;31m连接已断开\x1b[0m')

        // 尝试重连
        if (this.reconnectAttempts < this.maxReconnectAttempts) {
          this.reconnectAttempts++
          this.terminal.writeln(`\x1b[33m正在尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...\x1b[0m`)
          setTimeout(() => {
            this.connect()
          }, 2000)
        }
      }
    },

    handleConnectionError(message) {
      this.connectionStatus = 'error'
      this.terminal.writeln(`\r\n\x1b[1;31m连接错误: ${message}\x1b[0m`)
      this.cleanup()
    },

    handleTerminalInput(data) {
      if (this.websocket && this.connectionStatus === 'connected') {
        // 检测sz命令
        if (data.trim().startsWith('sz ')) {
          this.showSzCommandTip(data.trim())
        }

        this.websocket.send(JSON.stringify({
          type: 'input',
          data: data
        }))
      }
    },

    handleTerminalResize(size) {
      this.terminalSize = { cols: size.cols, rows: size.rows }

      if (this.websocket && this.connectionStatus === 'connected') {
        this.websocket.send(JSON.stringify({
          type: 'resize',
          cols: size.cols,
          rows: size.rows
        }))
      }
    },

    disconnect() {
      if (this.websocket) {
        this.websocket.send(JSON.stringify({
          type: 'disconnect'
        }))
      }
      this.cleanup()
    },

    goBack() {
      // 先断开连接
      this.disconnect()
      // 返回上一页
      this.$router.go(-1)
    },

    cleanup() {
      this.connectionStatus = 'disconnected'
      this.connectionId = null
      this.sessionStartTime = null

      if (this.websocket) {
        this.websocket.close()
        this.websocket = null
      }

      if (this.durationTimer) {
        clearInterval(this.durationTimer)
        this.durationTimer = null
      }
    },

    fitTerminal() {
      if (this.fitAddon) {
        this.fitAddon.fit()
      }
    },

    handleKeydown(event) {
      // 保留键盘事件处理，但移除全屏相关逻辑
    },

    handleResize() {
      this.$nextTick(() => {
        this.fitTerminal()
      })
    },

    startDurationTimer() {
      this.durationTimer = setInterval(() => {
        if (this.sessionStartTime) {
          this.sessionDuration = Math.floor((new Date() - this.sessionStartTime) / 1000)
        }
      }, 1000)
    },

    getStatusText() {
      const statusMap = {
        'disconnected': '未连接',
        'connecting': '连接中...',
        'connected': '已连接',
        'error': '连接错误'
      }
      return statusMap[this.connectionStatus] || '未知状态'
    },

    formatDuration(seconds) {
      const hours = Math.floor(seconds / 3600)
      const minutes = Math.floor((seconds % 3600) / 60)
      const secs = seconds % 60

      if (hours > 0) {
        return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
      } else {
        return `${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
      }
    },

    filterSystemMessages(output) {
      // 如果还没有连接成功，保留所有输出（包括登录信息）
      if (this.connectionStatus !== 'connected') {
        return output
      }

      // 只过滤真正不需要的系统消息，保留登录信息和shell提示符
      const systemMessagePatterns = [
        /^export DEBIAN_FRONTEND=noninteractive.*\r?\n/g,  // 过滤export命令
        /^unset MOTD_SHOWN.*\r?\n/g,  // 过滤unset命令
      ]

      let filteredOutput = output

      // 应用过滤规则
      systemMessagePatterns.forEach(pattern => {
        filteredOutput = filteredOutput.replace(pattern, '')
      })

      // 保留所有重要信息：Last login、系统信息、shell提示符等
      return filteredOutput
    },

    writeToTerminalBatched(output) {
      // 对于大量数据，分批写入以避免界面卡顿
      const chunkSize = 8192 // 8KB per chunk

      if (output.length <= chunkSize) {
        // 小数据直接写入
        this.terminal.write(output)
      } else {
        // 大数据分批写入
        let index = 0
        const writeChunk = () => {
          if (index < output.length) {
            const chunk = output.slice(index, index + chunkSize)
            this.terminal.write(chunk)
            index += chunkSize

            // 使用requestAnimationFrame确保不阻塞UI
            requestAnimationFrame(writeChunk)
          }
        }
        writeChunk()
      }
    },

    // 文件传输相关方法
    handleDragOver(e) {
      e.preventDefault()
      e.stopPropagation()
      this.isDragOver = true
    },

    handleDragLeave(e) {
      e.preventDefault()
      e.stopPropagation()
      // 只有当鼠标真正离开容器时才隐藏提示
      if (!this.$refs.terminalContainer.contains(e.relatedTarget)) {
        this.isDragOver = false
      }
    },

    handleDrop(e) {
      e.preventDefault()
      e.stopPropagation()
      this.isDragOver = false

      const files = Array.from(e.dataTransfer.files)
      if (files.length > 0) {
        this.uploadFilesSimple(files)
      }
    },

    async uploadFiles(files) {
      if (this.connectionStatus !== 'connected') {
        this.$message.error('请先连接SSH终端')
        return
      }

      if (this.isUploading) {
        this.$message.warning('正在上传文件，请稍候')
        return
      }

      this.isUploading = true
      this.uploadQueue = [...files]
      this.transferFiles = files.map(file => ({
        name: file.name,
        size: file.size,
        progress: 0,
        status: 'waiting' // waiting, uploading, completed, error
      }))

      this.fileTransferDialog = true
      this.transferType = 'upload'

      try {
        // 先获取当前工作目录
        const currentDir = await this.getCurrentWorkingDirectoryFromTerminal()

        // 使用HTTP API上传文件
        for (let i = 0; i < files.length; i++) {
          const file = files[i]
          const transferFile = this.transferFiles[i]

          transferFile.status = 'uploading'
          await this.uploadSingleFileViaAPI(file, transferFile, currentDir)
          transferFile.status = 'completed'
          transferFile.progress = 100
        }

        this.$message.success(`成功上传 ${files.length} 个文件`)

        // 在终端显示上传结果
        this.terminal.writeln(`\r\n\x1b[32m✅ 成功上传 ${files.length} 个文件到目录: ${currentDir}\x1b[0m`)
        this.terminal.writeln(`\x1b[90m提示: 使用 'ls -la' 查看上传的文件\x1b[0m`)

      } catch (error) {
        console.error('文件上传失败:', error)
        this.$message.error('文件上传失败: ' + error.message)
      } finally {
        this.isUploading = false
        setTimeout(() => {
          this.fileTransferDialog = false
        }, 2000)
      }
    },

    // 最简单的文件上传
    async uploadFilesSimple(files) {
      if (this.connectionStatus !== 'connected') {
        this.$message.error('请先连接SSH终端')
        return
      }

      try {
        // 获取当前工作目录
        const currentDir = await this.getCurrentWorkingDirectoryFromTerminal()

        // 逐个上传文件
        for (const file of files) {
          const formData = new FormData()
          formData.append('file', file)
          formData.append('target_path', currentDir)

          const response = await axios.post(`/api/hosts/${this.hostInfo.id}/upload-file/`, formData, {
            headers: { 'Content-Type': 'multipart/form-data' }
          })

          if (response.data.status !== 'success') {
            throw new Error(response.data.error || '上传失败')
          }
        }

        // 从响应中获取实际上传路径
        const actualPath = response.data.actual_path || currentDir
        this.terminal.writeln(`\r\n\x1b[32m✅ 成功上传 ${files.length} 个文件到: ${actualPath}\x1b[0m`)
        this.$message.success(`成功上传 ${files.length} 个文件`)

      } catch (error) {
        console.error('文件上传失败:', error)
        this.terminal.writeln(`\x1b[31m❌ 文件上传失败: ${error.message}\x1b[0m`)
        this.$message.error('文件上传失败')
      }
    },

    async waitForRzReady() {
      return new Promise((resolve) => {
        // 简单等待，实际项目中可以监听终端输出
        setTimeout(resolve, 500)
      })
    },

    async uploadSingleFileViaAPI(file, transferFile, targetPath = null) {
      const formData = new FormData()
      formData.append('file', file)
      formData.append('host_id', this.hostInfo.id)
      formData.append('target_path', targetPath || 'CURRENT_DIR')

      try {
        const response = await axios.post(`/api/hosts/${this.hostInfo.id}/upload-file/`, formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          },
          onUploadProgress: (progressEvent) => {
            const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total)
            transferFile.progress = progress
          }
        })

        if (response.data.status === 'success') {
          return response.data
        } else {
          throw new Error(response.data.error || '上传失败')
        }
      } catch (error) {
        transferFile.status = 'error'
        throw error
      }
    },

    // 下载文件
    downloadFile(filename) {
      if (this.connectionStatus !== 'connected') {
        this.$message.error('请先连接SSH终端')
        return
      }

      // 发送sz命令下载文件
      this.terminal.write(`sz ${filename}\r`)
      this.$message.info('开始下载文件: ' + filename)
    },

    // 显示文件传输对话框
    showFileTransferDialog() {
      this.fileTransferDialog = true
      // 如果是下载模式，自动加载文件列表
      if (this.transferType === 'download') {
        this.$nextTick(() => {
          this.loadFileList()
        })
      }
    },

    // 关闭文件传输对话框
    closeFileTransferDialog() {
      this.fileTransferDialog = false
    },

    // 处理文件选择
    handleFileSelect(event) {
      const files = Array.from(event.target.files)
      if (files.length > 0) {
        this.uploadFiles(files)
      }
    },

    // 格式化文件大小
    formatFileSize(bytes) {
      if (bytes === 0) return '0 Bytes'
      const k = 1024
      const sizes = ['Bytes', 'KB', 'MB', 'GB']
      const i = Math.floor(Math.log(bytes) / Math.log(k))
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
    },

    // 获取文件状态文本
    getFileStatusText(status) {
      const statusMap = {
        'waiting': '等待中',
        'uploading': '上传中',
        'completed': '已完成',
        'error': '失败'
      }
      return statusMap[status] || '未知'
    },

    // 文件浏览器相关方法
    async loadFileList() {
      this.fileBrowser.loading = true
      try {
        const response = await axios.get(`/api/hosts/${this.hostInfo.id}/list-files/`, {
          params: {
            path: this.fileBrowser.currentPath
          }
        })

        if (response.data.status === 'success') {
          this.fileBrowser.files = response.data.files
        } else {
          this.$message.error('获取文件列表失败: ' + response.data.error)
        }
      } catch (error) {
        console.error('获取文件列表失败:', error)
        this.$message.error('获取文件列表失败')
      } finally {
        this.fileBrowser.loading = false
      }
    },

    goToParentDirectory() {
      const currentPath = this.fileBrowser.currentPath
      if (currentPath === '/' || currentPath === '~') return

      const parentPath = currentPath.split('/').slice(0, -1).join('/') || '/'
      this.fileBrowser.currentPath = parentPath
      this.loadFileList()
    },

    selectFile(file) {
      if (file.type === 'file') {
        const filePath = file.path
        const index = this.fileBrowser.selectedFiles.indexOf(filePath)

        if (index > -1) {
          this.fileBrowser.selectedFiles.splice(index, 1)
        } else {
          this.fileBrowser.selectedFiles.push(filePath)
        }
      }
    },

    handleFileDoubleClick(file) {
      if (file.type === 'directory') {
        this.fileBrowser.currentPath = file.path
        this.fileBrowser.selectedFiles = []
        this.loadFileList()
      } else {
        this.downloadSingleFile(file)
      }
    },

    async downloadSingleFile(file) {
      try {
        const response = await axios.get(`/api/hosts/${this.hostInfo.id}/download-file/`, {
          params: {
            file_path: file.path
          },
          responseType: 'blob'
        })

        // 创建下载链接
        const url = window.URL.createObjectURL(new Blob([response.data]))
        const link = document.createElement('a')
        link.href = url
        link.setAttribute('download', file.name)
        document.body.appendChild(link)
        link.click()
        link.remove()
        window.URL.revokeObjectURL(url)

        this.$message.success('文件下载成功: ' + file.name)
      } catch (error) {
        console.error('文件下载失败:', error)
        this.$message.error('文件下载失败: ' + file.name)
      }
    },

    async downloadSelectedFiles() {
      if (this.fileBrowser.selectedFiles.length === 0) return

      try {
        const response = await axios.post(`/api/hosts/${this.hostInfo.id}/download-files/`, {
          file_paths: this.fileBrowser.selectedFiles
        }, {
          responseType: 'blob'
        })

        // 创建下载链接
        const url = window.URL.createObjectURL(new Blob([response.data]))
        const link = document.createElement('a')
        link.href = url
        link.setAttribute('download', `files_${Date.now()}.zip`)
        document.body.appendChild(link)
        link.click()
        link.remove()
        window.URL.revokeObjectURL(url)

        this.$message.success(`成功下载 ${this.fileBrowser.selectedFiles.length} 个文件`)
        this.fileBrowser.selectedFiles = []
      } catch (error) {
        console.error('批量下载失败:', error)
        this.$message.error('批量下载失败')
      }
    },

    getFileIcon(file) {
      if (file.type === 'directory') {
        return 'fa fa-folder'
      }

      const ext = file.name.split('.').pop().toLowerCase()
      const iconMap = {
        'txt': 'fa fa-file-text',
        'log': 'fa fa-file-text',
        'conf': 'fa fa-file-code',
        'config': 'fa fa-file-code',
        'js': 'fa fa-file-code',
        'py': 'fa fa-file-code',
        'sh': 'fa fa-file-code',
        'jpg': 'fa fa-file-image',
        'png': 'fa fa-file-image',
        'gif': 'fa fa-file-image',
        'pdf': 'fa fa-file-pdf',
        'zip': 'fa fa-file-archive',
        'tar': 'fa fa-file-archive',
        'gz': 'fa fa-file-archive'
      }

      return iconMap[ext] || 'fa fa-file'
    },

    getFileColor(file) {
      if (file.type === 'directory') {
        return '#a4f4ba'
      }

      const ext = file.name.split('.').pop().toLowerCase()
      const colorMap = {
        'txt': '#ffffff',
        'log': '#ffc107',
        'conf': '#00eaff',
        'config': '#00eaff',
        'js': '#f7df1e',
        'py': '#3776ab',
        'sh': '#4eaa25',
        'jpg': '#ff6b7a',
        'png': '#ff6b7a',
        'gif': '#ff6b7a',
        'pdf': '#dc3545',
        'zip': '#6f42c1',
        'tar': '#6f42c1',
        'gz': '#6f42c1'
      }

      return colorMap[ext] || '#ffffff'
    },

    formatFileTime(timestamp) {
      if (!timestamp) return '-'
      const date = new Date(timestamp * 1000)
      return date.toLocaleDateString() + ' ' + date.toLocaleTimeString()
    },

    // 处理路径输入，防抖加载
    handlePathInput() {
      // 清除之前的定时器
      if (this.pathInputTimer) {
        clearTimeout(this.pathInputTimer)
      }

      // 设置新的定时器，500ms后执行
      this.pathInputTimer = setTimeout(() => {
        this.loadFileList()
      }, 500)
    },



    // sz命令提示
    showSzCommandTip(command) {
      const filename = command.split(' ')[1]
      if (filename) {
        // 显示提示信息
        setTimeout(() => {
          this.terminal.writeln(`\r\n\x1b[33m💡 提示: 检测到sz命令\x1b[0m`)
          this.terminal.writeln(`\x1b[90m   如果下载失败，可以使用文件浏览器下载: ${filename}\x1b[0m`)
          this.terminal.writeln(`\x1b[90m   点击右上角"文件传输"按钮 → 切换到下载模式\x1b[0m`)
        }, 1000)
      }
    },

    // 切换到下载模式
    switchToDownload() {
      this.transferType = 'download'
      this.fileBrowser.selectedFiles = []
      this.$nextTick(() => {
        this.loadFileList()
      })
    },

    // 切换到上传模式
    switchToUpload() {
      this.transferType = 'upload'
      this.transferFiles = []
    },

    // 从终端获取当前工作目录 - 通过执行pwd获取真实路径
    async getCurrentWorkingDirectoryFromTerminal() {
      if (this.connectionStatus !== 'connected' || !this.websocket) {
        return '/root'
      }

      return new Promise((resolve) => {
        let pwdOutput = ''
        let pwdReceived = false

        // 设置临时输出处理器来捕获pwd命令的输出，不显示到终端
        this.tempOutputHandler = (data) => {
          if (data.type === 'output') {
            pwdOutput += data.data

            // 查找pwd命令的输出（以/开头的路径）
            const lines = pwdOutput.split('\n')
            for (const line of lines) {
              const trimmedLine = line.trim()
              if (trimmedLine.startsWith('/') && !trimmedLine.includes('pwd') && !pwdReceived) {
                pwdReceived = true
                this.currentWorkingDirectory = trimmedLine
                // 清除临时处理器
                this.tempOutputHandler = null
                console.log('获取到当前工作目录:', trimmedLine)
                resolve(trimmedLine)
                return
              }
            }
          }
          // 不调用writeToTerminalBatched，这样pwd命令的输出就不会显示到终端
        }

        // 发送pwd命令，但不显示到终端
        this.websocket.send(JSON.stringify({
          type: 'input',
          data: 'pwd\r'
        }))

        // 设置超时，避免无限等待
        setTimeout(() => {
          if (!pwdReceived) {
            this.tempOutputHandler = null
            console.log('PWD获取超时，使用默认目录')
            resolve('/root') // 默认返回root目录
          }
        }, 2000)
      })
    },

    // 获取当前工作目录
    async getCurrentWorkingDirectory() {
      if (this.connectionStatus !== 'connected' || !this.websocket) {
        return '~'
      }

      return new Promise((resolve) => {
        // 设置临时监听器
        const originalHandler = this.handleWebSocketMessage
        this.handleWebSocketMessage = (data, connectResolve, connectReject) => {
          if (data.type === 'pwd_response') {
            this.currentWorkingDirectory = data.pwd
            // 恢复原始处理器
            this.handleWebSocketMessage = originalHandler
            resolve(data.pwd)
            return
          }
          // 调用原始处理器处理其他消息
          originalHandler.call(this, data, connectResolve, connectReject)
        }

        // 发送获取pwd的请求
        this.websocket.send(JSON.stringify({
          type: 'get_pwd'
        }))

        // 设置超时
        setTimeout(() => {
          this.handleWebSocketMessage = originalHandler
          resolve(this.currentWorkingDirectory)
        }, 2000)
      })
    },

    // 在上传前更新当前工作目录
    async updateCurrentWorkingDirectory() {
      await this.getCurrentWorkingDirectory()
    }
  }
}
</script>

<style scoped>
.new-ssh-terminal {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: transparent;
  overflow: hidden;
}

.terminal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px 70px 15px 20px;
  margin: 10px;
  border-radius: 0;
  /* 直角 */
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.header-left {
  display: flex;
  align-items: center;
  gap: 20px;
}

.host-info {
  display: flex;
  align-items: center;
  gap: 8px;
  color: rgba(255, 255, 255, 0.9);
}

.hostname {
  font-weight: 600;
  color: #00eaff;
}

.host-ip {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.9em;
}

.connection-status {
  display: flex;
  align-items: center;
  gap: 8px;
}

.status-indicator {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  animation: pulse 2s infinite;
}

.status-indicator.disconnected {
  background: #ff4757;
}

.status-indicator.connecting {
  background: #ffa502;
}

.status-indicator.connected {
  background: #2ed573;
}

.status-indicator.error {
  background: #ff3838;
}

.status-text {
  color: rgba(255, 255, 255, 0.8);
  font-size: 0.9em;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 15px;
}

.session-info {
  color: rgba(255, 255, 255, 0.8);
  font-family: 'Monaco', monospace;
}

.controls {
  display: flex;
  gap: 8px;
}



.file-transfer-btn {
  background: rgba(164, 244, 186, 0.8) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  color: white !important;
  transition: all 0.3s ease !important;
}

.file-transfer-btn:hover {
  background: rgba(164, 244, 186, 1) !important;
  border-color: rgba(164, 244, 186, 0.5) !important;
  transform: translateY(-1px) !important;
}

/* 拖拽样式 */
.drag-over {
  border: 2px dashed rgba(164, 244, 186, 0.8) !important;
  background: rgba(164, 244, 186, 0.05) !important;
}

.drag-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(164, 244, 186, 0.1);
  backdrop-filter: blur(10px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  border-radius: 8px;
}

.drag-content {
  text-align: center;
  color: white;
}

.drag-icon {
  font-size: 48px;
  color: rgba(164, 244, 186, 0.8);
  margin-bottom: 16px;
}

.drag-content h3 {
  margin: 16px 0 8px 0;
  color: rgba(164, 244, 186, 0.9);
  font-weight: 500;
}

.drag-content p {
  margin: 0;
  color: rgba(255, 255, 255, 0.7);
  font-size: 14px;
}

/* 文件传输对话框样式 */
.file-transfer-content {
  padding: 20px 0;
}

.glass-panel {
  background: rgba(255, 255, 255, 0.05);
  backdrop-filter: blur(15px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  padding: 20px;
  margin-bottom: 20px;
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.3),
    inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

.upload-area {
  text-align: center;
}

.upload-drop-zone {
  border: 2px dashed rgba(164, 244, 186, 0.3);
  border-radius: 8px;
  padding: 40px 20px;
  transition: all 0.3s ease;
  cursor: pointer;
}

.upload-drop-zone:hover {
  border-color: rgba(164, 244, 186, 0.6);
  background: rgba(164, 244, 186, 0.05);
}

.upload-icon {
  font-size: 48px;
  color: rgba(164, 244, 186, 0.8);
  margin-bottom: 16px;
}

.upload-drop-zone h4 {
  margin: 16px 0 8px 0;
  color: rgba(255, 255, 255, 0.9);
  font-weight: 500;
}

.upload-drop-zone p {
  margin: 0 0 20px 0;
  color: rgba(255, 255, 255, 0.6);
  font-size: 14px;
}

.glass-button {
  background: rgba(164, 244, 186, 0.8) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  color: white !important;
  transition: all 0.3s ease !important;
  backdrop-filter: blur(10px) !important;
}

.glass-button:hover {
  background: rgba(164, 244, 186, 1) !important;
  border-color: rgba(164, 244, 186, 0.5) !important;
  transform: translateY(-1px) !important;
}

.transfer-progress h4 {
  margin: 0 0 16px 0;
  color: rgba(255, 255, 255, 0.9);
  font-weight: 500;
}

.file-item {
  margin-bottom: 16px;
}

.file-info {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
  gap: 8px;
}

.file-name {
  color: rgba(255, 255, 255, 0.9);
  font-weight: 500;
  flex: 1;
}

.file-size {
  color: rgba(255, 255, 255, 0.6);
  font-size: 12px;
}

.file-status {
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 4px;
  font-weight: 500;
}

.file-status.waiting {
  background: rgba(255, 193, 7, 0.2);
  color: #ffc107;
}

.file-status.uploading {
  background: rgba(0, 123, 255, 0.2);
  color: #007bff;
}

.file-status.completed {
  background: rgba(40, 167, 69, 0.2);
  color: #28a745;
}

.file-status.error {
  background: rgba(220, 53, 69, 0.2);
  color: #dc3545;
}

.download-area h4 {
  margin: 0 0 16px 0;
  color: rgba(255, 255, 255, 0.9);
  font-weight: 500;
}

.glass-input {
  margin-bottom: 12px;
}

.glass-input :deep(.el-input__wrapper) {
  background: rgba(255, 255, 255, 0.05) !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  backdrop-filter: blur(10px) !important;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1) !important;
}

.glass-input :deep(.el-input__inner) {
  color: white !important;
  background: transparent !important;
}

.glass-input :deep(.el-input__inner::placeholder) {
  color: rgba(255, 255, 255, 0.5) !important;
}

.download-tip {
  margin: 0;
  color: rgba(255, 255, 255, 0.6);
  font-size: 12px;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

/* 文件浏览器样式 */
.download-header {
  margin-bottom: 20px;
}

.download-header h4 {
  margin: 0 0 12px 0;
  color: rgba(255, 255, 255, 0.9);
  font-weight: 500;
}

.path-bar {
  margin-bottom: 16px;
}

.path-input {
  width: 100%;
}

.file-list {
  max-height: 400px;
  overflow-y: auto;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.2);
}

.file-list-header {
  padding: 12px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  gap: 8px;
  background: rgba(255, 255, 255, 0.02);
}

.file-items {
  max-height: 300px;
  overflow-y: auto;
}

.file-item-row {
  display: flex;
  align-items: center;
  padding: 8px 16px;
  cursor: pointer;
  transition: all 0.2s ease;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.file-item-row:hover {
  background: rgba(164, 244, 186, 0.1);
}

.file-item-row.selected {
  background: rgba(164, 244, 186, 0.2);
  border-left: 3px solid rgba(164, 244, 186, 0.8);
}

.file-icon {
  width: 24px;
  text-align: center;
  margin-right: 12px;
}

.file-icon i {
  font-size: 16px;
}

.file-info {
  flex: 1;
  min-width: 0;
}

.file-name {
  color: rgba(255, 255, 255, 0.9);
  font-weight: 500;
  margin-bottom: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-details {
  display: flex;
  gap: 16px;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.6);
}

.file-size {
  min-width: 60px;
}

.file-time {
  min-width: 120px;
}

.file-permissions {
  min-width: 80px;
  font-family: monospace;
}

.file-actions {
  margin-left: 12px;
}

.download-actions {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  text-align: center;
}

/* 滚动条样式 */
.file-list::-webkit-scrollbar,
.file-items::-webkit-scrollbar {
  width: 6px;
}

.file-list::-webkit-scrollbar-track,
.file-items::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.05);
  border-radius: 3px;
}

.file-list::-webkit-scrollbar-thumb,
.file-items::-webkit-scrollbar-thumb {
  background: rgba(164, 244, 186, 0.3);
  border-radius: 3px;
}

.file-list::-webkit-scrollbar-thumb:hover,
.file-items::-webkit-scrollbar-thumb:hover {
  background: rgba(164, 244, 186, 0.5);
}

/* 路径刷新按钮样式 */
.path-refresh-btn {
  background: rgba(164, 244, 186, 0.8) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  color: white !important;
  transition: all 0.3s ease !important;
  backdrop-filter: blur(10px) !important;
  border-radius: 0 8px 8px 0 !important;
  box-shadow:
    0 4px 16px rgba(164, 244, 186, 0.2),
    inset 0 1px 0 rgba(255, 255, 255, 0.1) !important;
}

.path-refresh-btn:hover {
  background: rgba(164, 244, 186, 1) !important;
  border-color: rgba(164, 244, 186, 0.5) !important;
  transform: translateY(-1px) !important;
  box-shadow:
    0 6px 20px rgba(164, 244, 186, 0.3),
    inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
}

.path-refresh-btn:active {
  transform: translateY(0) !important;
  box-shadow:
    0 2px 8px rgba(164, 244, 186, 0.2),
    inset 0 1px 0 rgba(255, 255, 255, 0.1) !important;
}

/* 修复输入框组合样式 */
.path-input :deep(.el-input-group__append) {
  background: transparent !important;
  border: none !important;
  padding: 0 !important;
}

.path-input :deep(.el-input-group__append .el-button) {
  margin: 0 !important;
  border-radius: 0 8px 8px 0 !important;
}

/* 文件导航按钮样式 */
.file-nav-button {
  background: rgba(164, 244, 186, 0.6) !important;
  border: 1px solid rgba(164, 244, 186, 0.2) !important;
  color: rgba(255, 255, 255, 0.9) !important;
  transition: all 0.3s ease !important;
  backdrop-filter: blur(8px) !important;
  border-radius: 6px !important;
  font-size: 12px !important;
  padding: 6px 12px !important;
  margin-right: 8px !important;
  box-shadow:
    0 2px 8px rgba(164, 244, 186, 0.1),
    inset 0 1px 0 rgba(255, 255, 255, 0.1) !important;
}

.file-nav-button:hover {
  background: rgba(164, 244, 186, 0.8) !important;
  border-color: rgba(164, 244, 186, 0.4) !important;
  color: white !important;
  transform: translateY(-1px) !important;
  box-shadow:
    0 4px 12px rgba(164, 244, 186, 0.2),
    inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
}

.file-nav-button:active {
  transform: translateY(0) !important;
  box-shadow:
    0 1px 4px rgba(164, 244, 186, 0.1),
    inset 0 1px 0 rgba(255, 255, 255, 0.1) !important;
}

.file-nav-button:disabled {
  background: rgba(164, 244, 186, 0.3) !important;
  border-color: rgba(164, 244, 186, 0.1) !important;
  color: rgba(255, 255, 255, 0.5) !important;
  cursor: not-allowed !important;
  transform: none !important;
  box-shadow: none !important;
}

.file-nav-button i {
  margin-right: 4px;
}

/* 文件下载按钮样式 */
.file-download-btn {
  background: rgba(164, 244, 186, 0.7) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  color: white !important;
  transition: all 0.3s ease !important;
  backdrop-filter: blur(6px) !important;
  border-radius: 4px !important;
  padding: 4px 8px !important;
  min-width: 32px !important;
  height: 28px !important;
  box-shadow:
    0 2px 6px rgba(164, 244, 186, 0.15),
    inset 0 1px 0 rgba(255, 255, 255, 0.1) !important;
}

.file-download-btn:hover {
  background: rgba(164, 244, 186, 0.9) !important;
  border-color: rgba(164, 244, 186, 0.5) !important;
  transform: translateY(-1px) scale(1.05) !important;
  box-shadow:
    0 4px 10px rgba(164, 244, 186, 0.25),
    inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
}

.file-download-btn:active {
  transform: translateY(0) scale(1) !important;
  box-shadow:
    0 1px 3px rgba(164, 244, 186, 0.15),
    inset 0 1px 0 rgba(255, 255, 255, 0.1) !important;
}

.file-download-btn i {
  font-size: 12px;
}

.terminal-container {
  flex: 1;
  margin: 0 10px;
  border-radius: 0;
  /* 直角 */
  overflow: hidden;
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  position: relative;
}



.xterm-container {
  height: 100%;
  padding: 10px;
}

.status-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 20px;
  margin: 10px;
  border-radius: 0;
  /* 直角 */
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 0.85em;
}

.status-left,
.status-right {
  display: flex;
  gap: 15px;
  color: rgba(255, 255, 255, 0.7);
}

.connection-id {
  color: #00eaff;
}

.terminal-size {
  font-family: 'Monaco', monospace;
}

@keyframes pulse {

  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.5;
  }
}



/* 响应式设计 */
@media (max-width: 768px) {
  .terminal-header {
    flex-direction: column;
    gap: 10px;
    padding: 10px;
  }

  .header-left,
  .header-right {
    width: 100%;
    justify-content: space-between;
  }

  .controls {
    flex-wrap: wrap;
  }
}

/* 精确的xterm颜色保护 - 只重置必要的样式 */
.terminal-container :deep(.xterm) {
  color: inherit !important;
  background-color: transparent !important;
}

/* 确保ANSI颜色类能正常工作 */
.terminal-container :deep(.xterm-fg-1) {
  color: #cd0000 !important;
}

.terminal-container :deep(.xterm-fg-2) {
  color: #00cd00 !important;
}

.terminal-container :deep(.xterm-fg-3) {
  color: #cdcd00 !important;
}

.terminal-container :deep(.xterm-fg-4) {
  color: #0000ee !important;
}

.terminal-container :deep(.xterm-fg-5) {
  color: #cd00cd !important;
}

.terminal-container :deep(.xterm-fg-6) {
  color: #00cdcd !important;
}

.terminal-container :deep(.xterm-fg-7) {
  color: #e5e5e5 !important;
}

/* 明亮颜色 */
.terminal-container :deep(.xterm-fg-9) {
  color: #ff0000 !important;
}

.terminal-container :deep(.xterm-fg-10) {
  color: #00ff00 !important;
}

.terminal-container :deep(.xterm-fg-11) {
  color: #ffff00 !important;
}

.terminal-container :deep(.xterm-fg-12) {
  color: #5c5cff !important;
}

.terminal-container :deep(.xterm-fg-13) {
  color: #ff00ff !important;
}

.terminal-container :deep(.xterm-fg-14) {
  color: #00ffff !important;
}

.terminal-container :deep(.xterm-fg-15) {
  color: #ffffff !important;
}

/* 使用与LunaSSH相同的xterm样式 - 只处理滚动条，不覆盖颜色 */
.terminal-container :deep(.xterm-viewport) {
  scrollbar-width: thin;
  scrollbar-color: rgba(164, 244, 186, 0.3) rgba(164, 244, 186, 0.1);
  overscroll-behavior: contain;
  padding-bottom: 10px;
}

.terminal-container :deep(.xterm-screen) {
  padding-bottom: 8px;
}

.terminal-container :deep(.xterm-viewport::-webkit-scrollbar) {
  width: 8px;
}

.terminal-container :deep(.xterm-viewport::-webkit-scrollbar-track) {
  background: rgba(164, 244, 186, 0.1);
}

.terminal-container :deep(.xterm-viewport::-webkit-scrollbar-thumb) {
  background: rgba(164, 244, 186, 0.3);
  border-radius: 4px;
}

.terminal-container :deep(.xterm-viewport::-webkit-scrollbar-thumb:hover) {
  background: rgba(164, 244, 186, 0.5);
}
</style>
